package main

import (
	"ascii-picture/assert"
	"flag"
	"fmt"
	"image"
	"image/color"
	"log"
	"os"
	"path/filepath"
	"runtime"

	"strconv"

	"github.com/nfnt/resize"

	"github.com/golang/freetype"
)

func createImage(textName string) (image.Image, error) {

	// imgfile, _ := os.Create(textName + ".png")
	// defer imgfile.Close()
	//创建位图,坐标x,y,长宽x,y
	img := image.NewNRGBA(image.Rect(0, 0, 160, 42))
	// 画背景,这里可根据喜好画出背景颜色
	for y := 0; y < 42; y++ {
		for x := 0; x < 160; x++ {
			//设置某个点的颜色，依次是 RGBA
			img.Set(x, y, color.RGBA{255, 255, 255, 255})
		}
	}
	//读字体数据
	// fontBytes, err := ioutil.ReadFile("data/simkai.ttf")
	fontBytes, err := assert.Asset("data/simkai.ttf")
	if err != nil {
		return nil, err
	}

	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		return nil, err
	}

	c := freetype.NewContext()
	c.SetDPI(72)
	c.SetFont(font)
	c.SetFontSize(40)
	c.SetClip(img.Bounds())
	c.SetDst(img)
	c.SetSrc(image.Black)
	//设置字体显示位置
	pt := freetype.Pt(1, 25+int(c.PointToFixed(40)>>8))
	_, err = c.DrawString(textName, pt)
	if err != nil {
		return nil, err
	}
	//保存图像到文件
	// err = png.Encode(imgfile, img)
	// if err != nil {
	// 	log.Fatal(err)
	// }
	return img, nil
}

func drawASCII(img image.Image) {
	//灰度替换字符
	base := "@#&$%*o!;."
	// file1, _ := os.Open(picName + ".png") //图像名称
	// img, _ := png.Decode(file1)
	bounds := img.Bounds() //获取图像的边界信息
	logo := ""             //存储最终的字符画string
	for y := 0; y < bounds.Dy(); y += 2 {
		for x := 0; x < bounds.Dx(); x++ {
			pixel := img.At(x, y)      //获取像素点
			r, g, b, _ := pixel.RGBA() //获取像素点的rgb
			r = r & 0xFF
			g = g & 0xFF
			b = b & 0xFF
			//灰度计算
			gray := 0.299*float64(r) + 0.578*float64(g) + 0.114*float64(b)
			temp := fmt.Sprintf("%.0f", gray*float64(len(base)+1)/255)
			index, _ := strconv.Atoi(temp)
			//根据灰度索引字符并保存
			if index >= len(base) {
				logo += " "
			} else {
				logo += string(base[index])
			}

		}
		logo += "\r\n"
	}
	// file1.Close()
	//输出字符画
	//log.Printf("\033[31;1m%s , %d", logo, len(logo))
	println(logo)
}

type commandOptions struct {
	help        bool
	logFileName string
	logFileSize int64
	logLevel    string
	maxProcs    int
	listen      string
	database    string
	encrypt     string
	dir         string
	user        string
	password    string
	debug       bool
	text        string
}

var (
	opt = commandOptions{}
)

func processCmdline() {
	// 设置命令行解析格式
	flag.BoolVar(&opt.help, "h", false, "this help")
	flag.StringVar(&opt.logFileName, "log", "", "log to `filename`")
	flag.StringVar(&opt.logLevel, "log-level", "debug", "log `level` [debug/info/warn/error/none]")
	flag.Int64Var(&opt.logFileSize, "log-size", 10*1024*1024, "log file max `size`")
	flag.IntVar(&opt.maxProcs, "cpu", 1, "use cpu `number` for goroutine")
	flag.StringVar(&opt.listen, "listen", "127.0.0.1:8888", "listen `address:port` for http server")
	flag.StringVar(&opt.database, "db", "account.aidb", "account database `file`")
	flag.StringVar(&opt.encrypt, "encrypt", "", "run command to encrypt `file` as <file>.aidb")
	flag.StringVar(&opt.dir, "d", "", "work `dir` (default current dir)")
	flag.StringVar(&opt.user, "u", "", "http server login `user`")
	flag.StringVar(&opt.password, "p", "", "http server login `password`")
	flag.BoolVar(&opt.debug, "debug", false, "log http request and response info")

	// 解析命令行，如果是显示帮助，则显示帮助后退出
	flag.Parse()
	opt.text = flag.Arg(0)
	if opt.help || opt.text == "" {
		flag.Usage()
		os.Exit(0)
	}
}

func main() {
	// 解析命令行
	processCmdline()

	// 设置程序使用的最大cpu数量
	runtime.GOMAXPROCS(opt.maxProcs)

	// 获取当前程序路径
	var err error
	if opt.dir == "" {
		if opt.dir, err = filepath.Abs(filepath.Dir(os.Args[0])); err != nil {
			log.Fatal(err)
		}
	}

	img, err := createImage(opt.text)
	if err != nil {
		log.Fatal(err)
	}
	img = resize.Resize(80, uint(img.Bounds().Dy()), img, resize.Lanczos3)
	drawASCII(img)
}
